from typing import List, Dict, Any
import csv, json, os
import pandas as pd


class FieldReflect:

    def __init__(
        self, main_field: str = "", association_field: str = "", rule: str = ""
    ):
        self.main_field = main_field
        self.association_field = association_field
        self.rule = rule


class Relation:

    def __init__(
        self,
        main: str = "",
        association: str = "",
        field_reflect: List[FieldReflect] = [],
    ):
        self.main = main
        self.association = association
        self.field_reflect = field_reflect


class StrutField:

    def __init__(
        self,
        field: str = "",
        field_type: str = "",
        rule: str = "",
        value: Any = "",
    ):
        self.field = field
        self.type = field_type
        self.rule = rule
        self.value = value


class Strut:

    def __init__(self, name: str = "", fields: List[StrutField] = []):
        self.name = name
        self.fields = fields


class TemplateRelation:

    def __init__(self, field: str = "", data_field: str = "", rule: str = ""):
        self.field = field
        self.data_field = data_field
        self.rule = rule


class FieldRule:
    def __init__(self, field: str = "", rule: str = ""):
        self.field = field
        self.rule = rule


class QuoteRule:
    def __init__(self, datas_rule: str = "", field_rule: List[FieldRule] = []):
        self.datas_rule = (
            datas_rule
            if datas_rule in ("sequence", "random", "average")
            else "sequence"
        )
        self.field_rule = field_rule


class ExtraData:
    def __init__(
        self,
        file: str = "",
        source: str = "",
        datas: list = [],
        quote_rule: QuoteRule = None,
    ):
        self.quote_rule = quote_rule
        self.datas = datas
        # 读取file路径内容，存入 self.datas中
        if source == "mount" and file is not None and file != "":
            # 读取file路径内容，存入 self.datas中
            mount_datas = self.read_file(file_path=file)
            if not mount_datas:
                return
            # 提取quote_rule中field_rule所包含的key
            field_rule = quote_rule.field_rule
            if not field_rule:
                self.datas = mount_datas
            else:
                # 提取field_rule中的所有字段
                field_keys = {item.field for item in field_rule}

                # 过滤mount_datas，创建新的字典列表
                self.datas = [
                    {
                        key: mount_data.get(key, "")
                        for key in mount_data
                        if key in field_keys
                    }
                    for mount_data in mount_datas
                ]

    def read_file(self, file_path):
        extension = os.path.splitext(file_path)[1].lower()
        if extension == ".csv":
            return self.read_csv(file_path)
        elif extension == ".xlsx":
            return self.read_excel(file_path)
        elif extension == ".json":
            return self.read_json(file_path)
        elif extension == ".txt":
            return self.read_txt(file_path)
        else:
            print(f"不支持的挂载文件类型: {extension}")
            return []

    def read_csv(self, file_path):
        data_list = []
        try:
            with open(file_path, mode="r", encoding="utf-8") as f:
                reader = csv.DictReader(f)
                for row in reader:
                    data_list.append(row)  # 直接将每一行字典添加到列表中
        except Exception as e:
            print(f"读取 CSV 文件发生错误 {file_path}: {e}")
        return data_list

    def read_excel(self, file_path):
        data_list = []
        try:
            df = pd.read_excel(file_path)
            data_list = df.to_dict(orient="records")  # 直接转换为字典列表
        except Exception as e:
            print(f"读取 Excel 文件发生错误 {file_path}: {e}")
        return data_list

    def read_json(self, file_path):
        data_list = []
        try:
            with open(file_path, mode="r", encoding="utf-8") as f:
                data = json.load(f)
                if isinstance(data, list):
                    data_list = data  # 如果是列表
                elif isinstance(data, dict):
                    data_list = [data]  # 如果是对象，转换为列表
                else:
                    print("不是一个合法的JSON字符串")
        except Exception as e:
            print(
                f"读取 JSON 文件发生错误 {file_path}，可能不是一个合法的JSON对象: {e}"
            )
        return data_list

    def read_txt(self, file_path):
        data_list = []
        try:
            with open(file_path, mode="r", encoding="utf-8") as f:
                # 使用文件名作为字典的键
                file_name = file_path.split("/")[-1].split(".")[0]  # 获取文件名
                for line in f:
                    line = line.strip()
                    if line:  # 只处理非空行
                        data_dict = {
                            file_name: line
                        }  # 创建字典，键为文件名，值为当前行
                        data_list.append(data_dict)  # 将字典添加到列表中
        except Exception as e:
            print(f"读取 TXT 文件发生错误 {file_path}: {e}")
        return data_list


class Template:

    def __init__(
        self,
        name: str = "",
        datas: List[Dict[str, Any]] = [],
        relations: List[TemplateRelation] = [],
        extra_datas: ExtraData = {},
    ):
        self.name = name
        self.datas = datas
        self.relations = relations
        self.extra_datas = extra_datas


class ExtraElements:

    def __init__(
        self, dbType: str = "", format: str = "", time: List = [], num: str = "1"
    ):
        self.dbType = dbType
        self.format = format
        self.time = time
        self.num = num


class DataStructure:
    def __init__(
        self,
        common_attrs: List[str] = [],
        common_attr_contents: List[Dict[str, Any]] = [],
        main: List[str] = [],
        association: List[str] = [],
        relation: List[Relation] = [],
        struts: List[Strut] = [],
        template: List[Template] = [],
        extra_elements: ExtraElements = [],
    ):
        self.common_attrs = common_attrs if common_attrs else []
        self.common_attr_contents = common_attr_contents if common_attr_contents else []
        self.main = main if main else []
        self.association = association if association else []
        self.relation = relation if relation else []
        self.struts = struts if struts else []
        self.template = template if template else []
        self.extra_elements = extra_elements if extra_elements else []


def create_data_structure(data: Dict[str, Any]) -> DataStructure:
    relations = [
        Relation(
            main=rel.get("main", ""),
            association=rel.get("association", ""),
            field_reflect=[FieldReflect(**fr) for fr in rel.get("field_reflect", [])],
        )
        for rel in data.get("relation", [])
    ]

    struts = [
        Strut(
            name=strut_name,
            fields=[
                StrutField(
                    field=f.get("field", ""),
                    field_type=f.get("type", ""),
                    rule=f.get("rule", ""),
                )
                for f in fields
            ],
        )
        for strut_name, fields in data.get("struts", {}).items()
    ]

    templates = [
        Template(
            name=template.get("name", ""),
            datas=template.get("datas", []),
            relations=[
                TemplateRelation(**relation)
                for relation in template.get("relation", [])
            ],
            extra_datas=ExtraData(
                file=template.get("extra_datas", {}).get("file", ""),
                source=template.get("extra_datas", {}).get("source", ""),
                datas=template.get("extra_datas", {}).get("datas", []),
                quote_rule=QuoteRule(
                    template.get("extra_datas", {})
                    .get("quote_rule", {})
                    .get("datas_rule", ""),
                    [
                        FieldRule(key, value)
                        for key, value in template.get("extra_datas", {})
                        .get("quote_rule", {})
                        .get("field_rule", {})
                        .items()
                        if isinstance(
                            template.get("extra_datas", {})
                            .get("quote_rule", {})
                            .get("field_rule", {}),
                            dict,
                        )
                    ],
                ),
            ),
        )
        for template in data.get("template", [])
    ]

    extra_elements = ExtraElements(
        dbType=data.get("extra_elements", {}).get("dbType", ""),
        format=data.get("extra_elements", {}).get("format", ""),
        time=data.get("extra_elements", {}).get("time", []),
        num=data.get("extra_elements", {}).get("num", "1"),
    )

    return DataStructure(
        common_attrs=data.get("common_attrs", []),
        common_attr_contents=data.get("common_attr_contents", {}),
        main=data.get("main", []),
        association=data.get("association", []),
        relation=relations,
        struts=struts,
        template=templates,
        extra_elements=extra_elements,
    )


__all__ = [
    "create_data_structure",
    "DataStructure",
    "ExtraElements",
    "ExtraData",
    "QuoteRule",
    "FieldRule",
    "Template",
    "TemplateRelation",
    "Strut",
    "StrutField",
    "Relation",
    "FieldReflect",
]
